//
//  Check.swift
//  NetWork
//
//  Created by Delin Meng 孟德林 on 2018/9/21.
//  Copyright © 2018年 Delin Meng 孟德林. All rights reserved.
//  校验类

import Foundation

class Check: NSObject {

    

    /// 比较完善的身份证验证
    ///
    /// - Parameter str:
    /// - Returns:
    static func isIDCard(str:String) -> Bool {

        if str.isEmpty || !isLegalIdCardLength(idCardNo: str)  { return false }
        //把15位身份证号转换为18位
        var convertedIdCardNo = str
        convert15IdTo18ID(idCardNo: &convertedIdCardNo)
        //检查地区码
        if !isLegalAreaCode(idCardNo: convertedIdCardNo) {
            return false
        }
        //检查生日
        if !isLegalBirthday(idCardNo: convertedIdCardNo) {
            return false
        }
        return true
    }

    private static func isLegalIdCardLength(idCardNo: String) -> Bool {
        let regex = "^(\\d{14}|\\d{17})(\\d|[xX])$"
        let identityCardPredicate = NSPredicate.init(format: "SELF MATCHES %@", regex)
        return identityCardPredicate.evaluate(with: idCardNo)
    }

    private static func convert15IdTo18ID(idCardNo:inout String) {
        //        if idCardNo.characters.count == 15 {
        //            idCardNo.insert(contentsOf: "19".characters, at: idCardNo.index(idCardNo.startIndex, offsetBy: 6))
        //            let computedChecksum =  computeCheckSum(idCardNo: idCardNo)
        //            idCardNo.insert(contentsOf: computedChecksum.characters, at: idCardNo.endIndex)
        //        }
        //如果包含了小写x，统一处理为大写X
        idCardNo = idCardNo.replacingOccurrences(of: "x", with: "X")
    }

    private static func isLegalAreaCode(idCardNo: String) -> Bool {
        let endIndex = idCardNo.index(idCardNo.startIndex, offsetBy: 2)
        let areaCode:String = idCardNo.substring(to: endIndex)
        var areaCodes: [String: String] = ["11" : "北京" ,
                                           "12" : "天津" ,
                                           "13" : "河北" ,
                                           "14" : "山西" ,
                                           "15" : "内蒙古",
                                           "21" : "辽宁" ,
                                           "22" : "吉林" ,
                                           "23" : "黑龙江",
                                           "31" : "上海" ,
                                           "32" : "江苏" ,
                                           "33" : "浙江" ,
                                           "34" : "安徽" ,
                                           "35" : "福建" ,
                                           "36" : "江西" ,
                                           "37" : "山东" ,
                                           "41" : "河南" ,
                                           "42" : "湖北" ,
                                           "43" : "湖南" ,
                                           "44" : "广东" ,
                                           "45" : "广西" ,
                                           "46" : "海南" ,
                                           "50" : "重庆" ,
                                           "51" : "四川" ,
                                           "52" : "贵州" ,
                                           "53" : "云南" ,
                                           "54" : "西藏" ,
                                           "61" : "陕西" ,
                                           "62" : "甘肃" ,
                                           "63" : "青海" ,
                                           "64" : "宁夏" ,
                                           "65" : "新疆" ,
                                           "71" : "台湾" ,
                                           "81" : "香港" ,
                                           "82" : "澳门" ,
                                           "91" : "国外"]
        if (areaCodes[areaCode] == nil) {
            return false
        } else {
            return true
        }
    }

    private static func isLegalBirthday(idCardNo:String) -> Bool {
        //年
        let yearStart = idCardNo.index(idCardNo.startIndex, offsetBy: 6)
        let yearEnd = idCardNo.index(idCardNo.endIndex, offsetBy: -8)
        let yearRange = yearStart..<yearEnd

        //月
        let monthStart = idCardNo.index(idCardNo.startIndex, offsetBy: 10)
        let monthEnd = idCardNo.index(idCardNo.endIndex, offsetBy: -6)
        let monthRange = monthStart..<monthEnd

        //日
        let dayStart = idCardNo.index(idCardNo.startIndex, offsetBy: 12)
        let dayEnd = idCardNo.index(idCardNo.endIndex, offsetBy: -4)
        let dayRange = dayStart..<dayEnd

        let year = idCardNo[yearRange]
        let month = idCardNo[monthRange]
        let day = idCardNo[dayRange]

        let dateFormatter:DateFormatter = DateFormatter()
        dateFormatter.dateStyle           = DateFormatter.Style.medium
        dateFormatter.timeStyle           = DateFormatter.Style.none
        dateFormatter.timeZone            = NSTimeZone.local
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        let date = dateFormatter.date(from: "\(year)-\(month)-\(day) 12:01:01")
        if date == nil {
            return false
        }
        return true
    }

    private static func isLegalCheckSum(idCardNo:String) -> Bool {
        let computedChecksum = computeCheckSum(idCardNo: idCardNo)

        let start = idCardNo.index(idCardNo.startIndex, offsetBy: 16)
        let end = idCardNo.index(idCardNo.endIndex, offsetBy: -1)
        let range = start..<end

        let checksum = idCardNo[range]
        if computedChecksum != checksum {
            return false
        }
        return true
    }

    private static func computeCheckSum(idCardNo:String) ->String {
        let R:[Int]          = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
        let checksumMap:[String] = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"]
        //        let sum = R.enumerated().reduce(0) {
        //            return $0 + Int(String(idCardNo[$1.0]))! * $1.1
        //        }
        //        return checksumMap[sum % 11]
        return ""
    }





}
